package route

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/ethclient"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"go-chain-api/api"
	"go-chain-api/global"
	models "go-chain-api/internal/model"
	"go-chain-api/tools"
	"go-chain-api/utils"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.uber.org/zap"
	"log"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"time"
)

// PaginationValidator 校验分页参数
func PaginationValidator() gin.HandlerFunc {
	return func(c *gin.Context) {
		pageStr := c.Query("pageIndex")
		perPageStr := c.Query("pageSize")

		language := c.Request.Header.Get("language")
		if pageStr == "" || perPageStr == "" {
			response := utils.GetResponse(nil, utils.ParamNotNull, nil, language)
			c.JSON(http.StatusBadRequest, response)
			c.Abort()
			return
		}

		page, err := strconv.Atoi(pageStr)
		if err != nil || page <= 0 {
			response := utils.GetResponse(nil, utils.PageParamInvalid, nil, language)
			c.JSON(http.StatusBadRequest, response)
			c.Abort()
			return
		}

		perPage, err := strconv.Atoi(perPageStr)
		if err != nil || perPage <= 0 {
			response := utils.GetResponse(nil, utils.PageParamInvalid, nil, language)
			c.JSON(http.StatusBadRequest, response)
			c.Abort()
			return
		}

		c.Set("pageIndex", uint((page-1)*perPage))
		c.Set("pageSize", uint(perPage))
		c.Next()
	}
}

// HeaderValidator 检验header
func HeaderValidator() gin.HandlerFunc {
	return func(c *gin.Context) {
		language := c.Request.Header.Get("language")
		if language == "" {
			language = "zh-tw"
		}
		chainName := c.Request.Header.Get("chain-name")
		if chainName == "" {
			response := utils.GetResponse(nil, utils.MissChainName, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}

		chainId := c.Request.Header.Get("chain-id")
		if chainId == "" {
			response := utils.GetResponse(nil, utils.MissChainId, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}

		chainUint, err := strconv.ParseUint(chainId, 10, 0)
		if err != nil {
			response := utils.GetResponse(nil, utils.ParseDataError, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}

		c.Set("chainName", strings.ToUpper(chainName))
		c.Set("chainId", uint(chainUint))
		c.Set("language", strings.ToUpper(language))
		c.Next()
	}
}

var (
	mutex        sync.Mutex
	isProcessing bool
)

func preventConcurrentAccess() gin.HandlerFunc {
	return func(c *gin.Context) {
		mutex.Lock()
		if isProcessing {
			c.JSON(http.StatusTooManyRequests, gin.H{"msg": "Request is already being processed", "code": utils.TooManyRequests})
			c.Abort()
			mutex.Unlock()
			return
		}

		// 设置正在处理状态
		isProcessing = true
		mutex.Unlock() // 释放锁，让其他请求可以检查状态

		defer func() {
			mutex.Lock()
			isProcessing = false
			mutex.Unlock()
		}()

		c.Next() // 继续处理请求
	}
}

// HeaderAuthValidator 校验header授权
func HeaderAuthValidator() gin.HandlerFunc {
	return func(c *gin.Context) {
		if c.Request.RequestURI == "/api/v2/register" || c.Request.RequestURI == "/api/v2/login" || c.Request.RequestURI == "/api/v2/productUpgrade" || c.Request.RequestURI == "/api/v2/generateAddress" || c.Request.RequestURI == "/api/v2/withdraw" || c.Request.RequestURI == "/api/v2/delAddress" {
			c.Next()
			return
		}
		language := c.Request.Header.Get("language")
		if language == "" {
			language = "zh-cn"
		}

		auth := c.Request.Header.Get("Authorization")
		if auth == "" {
			response := utils.GetResponse(nil, utils.AuthorizationError, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}
		// 获取授权信息
		var user models.User
		err, userInfo := user.CheckApiKey(auth)
		if err != nil {
			response := utils.GetResponse(nil, utils.UserNotExist, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}

		c.Set("userInfo", userInfo)
		c.Set("apiKey", auth)
		c.Set("language", language)

		if c.Request.Header.Get("chain-id") != "" {
			num, err := strconv.ParseUint(c.Request.Header.Get("chain-id"), 10, 0)
			if err != nil {
				response := utils.GetResponse(nil, utils.ParseDataError, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			ChainId := uint(num)
			c.Set("chainId", ChainId)
		}

		if c.Request.Header.Get("chain-name") != "" {
			//根据chainName获取链的连接信息
			chainName := strings.ToUpper(c.Request.Header.Get("chain-name"))
			c.Set("chainName", chainName)
		}
		c.Next()
	}
}

func RecoveryMiddleware() gin.HandlerFunc {

	return func(c *gin.Context) {
		defer func() {
			if err := recover(); err != nil {
				// 在这里处理异常，例如记录日志或返回特定的错误信息给客户端
				log.Println("Recovered from panic:", err)
				response := global.Response{
					Code: http.StatusInternalServerError,
					Data: nil,
					Msg:  "Recovered from panic:" + err.(string),
				}
				c.JSON(http.StatusOK, response)
				return
			}
		}()
		c.Next()
	}
}

// RegisterRoute 注册路由
func RegisterRoute() *gin.Engine {
	router := gin.Default()
	// 允许所有来源、方法、头部
	routerConfig := cors.DefaultConfig()
	routerConfig.AllowAllOrigins = true
	routerConfig.AllowMethods = []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}
	routerConfig.AllowHeaders = []string{"*"}

	// 区块链浏览器
	blockApi := api.Block{}
	// dapp
	dappApi := api.Dapp{}

	udunAPI := api.UdunAPI{}

	swapApi := api.Swap{}

	robotApi := api.Robot{}

	userApi := api.UserAPI{}
	//router.Use(LoggerMiddleware(logger))
	// 添加到 gin 路由
	router.Use(cors.New(routerConfig))
	//router.Use(RecoveryMiddleware())
	v1 := router.Group("/api/v1", HeaderValidator())
	// 获取最近出块信息
	v1.GET("/getBlockLast20", blockApi.GetLastBlocks)
	// 获取区块列表分页
	v1.GET("/getBlockByPage", PaginationValidator(), blockApi.GetBlockByPage)
	// 根据区块号获取区块信息
	v1.GET("/getBlockByNumber", blockApi.GetBlockByNumber)
	// 获取最近的交易信息
	v1.GET("/getTxRecords", PaginationValidator(), blockApi.GetTxRecords)
	// 获取交易信息
	v1.GET("/getTxByHash", blockApi.GetTxByHash)
	// 根据地址查询交易记录
	v1.GET("/getTxByAddress", PaginationValidator(), blockApi.GetTxByAddress)
	// 查询代币转账记录
	v1.GET("/getTokensRecords", PaginationValidator(), blockApi.GetTokensRecords)
	// 根据代币地址查询持有人数
	v1.GET("/getTokenHolders", blockApi.GetTokenHolders)
	// 根据代币地址查询总转账数
	v1.GET("/getTokenTransferCount", blockApi.GetTokenTransferCount)
	// 根据代币地址查询总转账额
	v1.GET("/getTokenTransferAmount", blockApi.GetTokenTransferAmount)
	// 查询最少的手续费
	v1.GET("/getMinerFee", blockApi.GetMinerFee)
	// 查询手续费总数
	v1.GET("/getFeeTotal", blockApi.GetFeeTotal)
	// 获取代币列表
	v1.GET("/getTokenList", blockApi.GetTokenList)
	// 获取余额
	v1.GET("/getBalance", blockApi.GetBalance)
	//判断地址是不是合约
	v1.GET("/isContractAddress", blockApi.IsContractAddress)
	//新增兑换申请
	v1.POST("/createChainApply", blockApi.Create)
	//查询兑换申请
	v1.GET("/getChainApplyList", blockApi.List)
	//获取代币列表
	v1.GET("/getChainTokenList", blockApi.TokenList)
	//获取链列表
	v1.GET("/getApiList", blockApi.ApiList)
	//获取比例
	v1.GET("/getRate", blockApi.GetRate)
	//合约搜索
	v1.GET("/getTokenInfo", blockApi.GetTokenInfo)
	//根据地址查询买入卖出
	v1.GET("/getRecordByAddress", PaginationValidator(), blockApi.GetRecordByAddress)
	//获取代币的当前价格
	v1.GET("/getPrice", blockApi.GetPrice)

	// v2 付费接口
	v2 := router.Group("/api/v2", HeaderAuthValidator())
	// 注册用户
	v2.POST("/register", dappApi.Register)
	// 登录
	v2.POST("/login", dappApi.Login)
	// 获取归集数据
	v2.GET("/collectionRecord", PaginationValidator(), HeaderValidator(), dappApi.GetCollectionList)
	// 修改归集记录
	v2.PUT("/collectionRecord", HeaderValidator(), dappApi.UpdateCollectionRecord)
	// 添加监听地址
	v2.POST("/watchAddress", dappApi.AddWatchAddress)
	// 获取监听地址
	v2.GET("/watchAddress", PaginationValidator(), dappApi.GetWatchAddress)
	// 删除监听地址
	v2.DELETE("/watchAddress/:id", dappApi.DelWatchAddress)
	//生成地址
	v2.POST("/generateAddress", VerifySign(), udunAPI.GenerateAddress)
	//根据地址删除
	v2.POST("/delAddress", VerifyDel(), udunAPI.DelAddress)
	//获取代币列表
	v2.GET("/getUserTokens", PaginationValidator(), udunAPI.GetUserTokens)
	//修改回调地址
	v2.POST("/updateCallBackUrl", udunAPI.UpdateCallBackUrl)
	//用户添加币种
	v2.POST("/addToken", VerifyTime(), udunAPI.AddToken)
	//获取所有币种列表
	v2.GET("/getAllTokenList", udunAPI.GetAllTokenList)
	//获取用户添加的币种
	v2.GET("/getUserTokenList", PaginationValidator(), udunAPI.GetUserTokenList)
	//获取币种信息
	v2.GET("/getTokenInfo", udunAPI.GetTokenInfo)
	//上币申请
	v2.POST("/addApplyToken", VerifyTime(), udunAPI.AddApplyToken)
	//上币申请列表
	v2.GET("/getApplyTokenList", PaginationValidator(), udunAPI.GetApplyTokenList)
	//获取地址
	v2.GET("/getUserAddress", PaginationValidator(), udunAPI.GetUserAddress)
	//获取订单列表
	v2.GET("/getOrderList", PaginationValidator(), udunAPI.GetOrderList)
	//取消订单
	v2.POST("/cancelOrder", udunAPI.CancelOrder)
	//提币申请
	v2.POST("/withdraw", VerifySign(), udunAPI.Withdraw)
	//同意或拒绝提币申请
	v2.POST("/changeWithdrawStatus", udunAPI.ChangeWithdrawStatus)
	//提币列表
	v2.GET("/withdrawList", PaginationValidator(), udunAPI.WithdrawList)
	//获取配置列表
	v2.GET("/getConfigList", udunAPI.GetConfigList)
	//产品升级
	v2.POST("/productUpgrade", udunAPI.ProductUpgrade)
	//充币列表
	v2.GET("/getUpCoinList", PaginationValidator(), udunAPI.GetUpCoinList)
	//获取用户监听的回调列表
	v2.GET("/getCallbackList", PaginationValidator(), udunAPI.GetCallbackList)
	//获取产品列表
	v2.GET("/getProductList", udunAPI.GetProductList)
	//回调补发
	v2.POST("/callbackReissue", udunAPI.CallbackReissue)
	//首页信息
	v2.GET("/index", udunAPI.Index)
	//资产管理
	v2.POST("/addPocketAddress", VerifyTime(), udunAPI.AddPocketAddress)
	//资产管理列表
	v2.GET("/getPocketList", PaginationValidator(), udunAPI.GetPocketList)
	//修改资产管理
	v2.POST("/updatePocketAddress", udunAPI.UpdatePocketAddress)
	//获取资产详情
	v2.GET("/getPocketInfo", udunAPI.GetPocketInfo)
	//删除资产管理
	v2.POST("/deletePocketAddress", udunAPI.DeletePocketAddress)
	//更新手续费地址或者提现地址
	v2.POST("/updateAddress", udunAPI.UpdateAddress)
	//把提现地址和手续费地址提现到归集地址
	v2.POST("/withdrawToCollect", udunAPI.WithdrawToCollection)
	//用户升级获取生成地址
	v2.POST("/createOrder", udunAPI.CreateOrder)
	//获取用户到期时间
	v2.GET("/getMaturityTime", udunAPI.GetMaturityTime)
	//获取用户是否有待支付订单
	v2.GET("/getPayOrder", udunAPI.GetPayOrder)
	//确认支付
	v2.POST("/confirmPayOrder", udunAPI.ConfirmPayOrder)
	//手动归集
	v2.POST("/manualCollection", preventConcurrentAccess(), VerifyTime(), udunAPI.ManualCollection)
	//获取email
	v2.GET("/getEmail", userApi.GetEmail)
	//修改提币审核状态
	v2.POST("/setVerifyStatus", userApi.SetVerifyStatus)
	//获取提币审核状态
	v2.GET("/getVerifyStatus", userApi.GetVerifyStatus)

	//获取底池列表
	v2.GET("/getPoolList", PaginationValidator(), swapApi.GetPoolList)
	//获取底池交易列表
	v2.GET("/getPoolTxList", PaginationValidator(), swapApi.GetPoolTxList)
	//添加底池信息
	v2.POST("/createSwapInfo", swapApi.CreateSwapInfo)
	//创建机器人
	v2.POST("/createRobot", robotApi.CreateRobot)
	//机器人列表
	v2.GET("/getRobotList", PaginationValidator(), robotApi.GetRobotList)
	//根据合约地址获取代币地址
	v2.GET("/getTokenByAddress", robotApi.GetTokenByAddress)
	//获取机器人详情
	v2.GET("/getRobotDetail", robotApi.GetRobotDetail)
	//删除机器人
	v2.GET("/delRobot", robotApi.DelRobot)
	//机器人改名
	v2.POST("/renameRobot", robotApi.RenameRobot)
	//开启或关闭机器人
	v2.GET("/editStatusRobot", robotApi.EditStatusRobot)
	//机器人查询余额
	v2.GET("/getRobotBalance", robotApi.GetRobotBalance)
	//修改用户邮箱
	v2.POST("/setUserEmail", userApi.SetUserEmail)
	//获取验证码
	v2.GET("/getRedisEmailCode", userApi.GetRedisEmailCode)

	//获取验证码
	router.GET("/api/v2/getEmailCode", userApi.GetEmailCode)

	//重置密码
	router.POST("/api/v2/resetPassword", userApi.ResetPassword)
	//生成支付地址
	router.POST("/api/v2/createPayAddress", userApi.CreatePayAddress)

	//批量修改用户钱包地址
	router.POST("/api/v2/batchUpdatePocket", udunAPI.BatchUpdatePocket)
	//批量修改用户生成的地址
	router.POST("/api/v2/batchUpdateAddress", udunAPI.BatchUpdateAddress)
	return router
}

func VerifySign() gin.HandlerFunc {
	return func(c *gin.Context) {

		contentType := c.Request.Header.Get("Content-Type")
		var userId string
		var mainCoinType int64
		var coinType string
		var typeVal string
		var productId string
		var amount string
		var businessId string
		var memo string
		var address string
		var callBackUrl string
		var nonce string
		var timestamp string
		var sign string
		var bodyJson string

		language := c.Request.Header.Get("language")
		if language == "" {
			language = "zh-tw"
		}

		if !strings.Contains(contentType, "application/json") {
			bodyJson = c.PostForm("body")
			if bodyJson == "" {
				response := utils.GetResponse(nil, utils.ParseDataError, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			nonce = c.PostForm("nonce")
			if nonce == "" {
				response := utils.GetResponse(nil, utils.NonceNotEmpty, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			timestamp = c.PostForm("timestamp")
			if timestamp == "" {
				response := utils.GetResponse(nil, utils.TimeStampNotEmpty, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			sign = c.PostForm("sign")
			if sign == "" {
				response := utils.GetResponse(nil, utils.SignNotEmpty, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}

			//解析body
			var body models.Body
			err := json.Unmarshal([]byte(bodyJson), &body)
			if err != nil {
				response := utils.GetResponse(nil, utils.BodyParseError, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}

			address = body.Address
			memo = body.Memo
			businessId = body.BusinessId
			amount = body.Amount
			callBackUrl = body.CallUrl
			userId = body.MerchantId
			coinType = body.CoinType
			typeVal = c.DefaultPostForm("type", "0")
			productId = c.PostForm("productId")
			mainCoinType = int64(body.MainCoinType)

		} else {
			var requestParam models.RequestParam
			err := c.ShouldBindJSON(&requestParam)
			if err != nil {
				response := utils.GetResponse(err, utils.ParamBindError, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}

			var body models.Body
			err = json.Unmarshal([]byte(requestParam.Body), &body)
			if err != nil {
				response := utils.GetResponse(err, utils.BodyParseError, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}

			if requestParam.Nonce == "" {
				response := utils.GetResponse(nil, utils.NonceNotEmpty, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			if requestParam.Timestamp == "" {
				response := utils.GetResponse(nil, utils.TimeStampNotEmpty, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			if requestParam.Sign == "" {
				response := utils.GetResponse(nil, utils.SignNotEmpty, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			userId = body.MerchantId
			mainCoinType = int64(body.MainCoinType)
			coinType = body.CoinType
			typeVal = requestParam.Type
			productId = requestParam.ProductId
			amount = body.Amount
			businessId = body.BusinessId
			memo = body.Memo
			address = body.Address
			nonce = requestParam.Nonce
			timestamp = requestParam.Timestamp
			sign = requestParam.Sign
			callBackUrl = body.CallUrl
			bodyJson = requestParam.Body
		}

		//查询用户信息
		user := new(models.User)
		//string转ObjectId
		objId, err := primitive.ObjectIDFromHex(userId)
		if err != nil {
			response := utils.GetResponse(err, utils.ParseDataError, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}
		userClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")
		err = userClient.FindOne(context.TODO(), bson.D{{"_id", objId}}).Decode(&user)
		if err != nil {
			response := utils.GetResponse(err, utils.GetError, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}
		if user.Status == 0 || (user.MaturityTime < time.Now().Unix() && user.DappMaturityTime < time.Now().Unix()) {
			response := utils.GetResponse(nil, utils.UserNotMemberOrStop, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}

		if c.Request.RequestURI == "/api/v2/generateAddress" && user.MaturityTime < time.Now().Unix() {
			response := utils.GetResponse(nil, utils.UserNotMemberOrStop, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}

		//主币编号验证
		var scanConfig models.ScanConfig
		configClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("scan_config")
		err = configClient.FindOne(context.TODO(), bson.D{{"udunId", mainCoinType}, {"type", "DAPP"}}).Decode(&scanConfig)
		if err != nil {
			response := utils.GetResponse(err, utils.MainCoinTypeInvalid, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}
		var clients *ethclient.Client
		if scanConfig.ChainName != "TRX" {
			clients, err = ethclient.Dial(scanConfig.RpcUrl)
			if err != nil {
				response := utils.GetResponse(err, utils.ConnectRpcUrlError, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}

		}

		if c.Request.RequestURI == "/api/v2/withdraw" {
			var tokenInfo models.TokenInfo
			tokenClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("token")
			var coinTypeStr string
			if scanConfig.ChainName != "TRX" {
				if len(coinType) == 42 {
					coinTypeStr = common.HexToAddress(coinType).Hex()
				} else {
					coinTypeStr = coinType
				}
			}

			var flag bool
			if scanConfig.ChainName == "TRX" {
				coinTypeStr = coinType

				flag = tools.IsValidTRXAddress(address)
			} else {
				flag = tools.IsValidEVMAddress(address)
			}

			if !flag {
				response := utils.GetResponse(err, utils.AddressFormatError, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}

			err = tokenClient.FindOne(context.TODO(), bson.D{{"address", coinTypeStr}}).Decode(&tokenInfo)
			if err != nil {
				response := utils.GetResponse(err, utils.GetError, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			c.Set("tokenInfo", tokenInfo)
		}

		c.Set("chainConfig", scanConfig)
		c.Set("callBack", callBackUrl)
		c.Set("user_id", userId)
		c.Set("type", typeVal)
		c.Set("product_id", productId)

		c.Set("amount", amount)
		c.Set("businessId", businessId)
		c.Set("memo", memo)
		c.Set("address", address)
		c.Set("client", clients) // 存储*ethClient.Client实例到Gin上下文
		c.Set("language", language)

		//验证签名
		isOk := tools.VerifySign(bodyJson, user.ApiKey, nonce, timestamp, sign)
		if !isOk {
			response := utils.GetResponse(nil, utils.SignError, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}

		c.Next()

	}
}

func VerifyTime() gin.HandlerFunc {
	return func(c *gin.Context) {
		auth := c.Request.Header.Get("Authorization")
		language := c.Request.Header.Get("language")
		if auth == "" {
			response := utils.GetResponse(nil, utils.AuthorizationError, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}
		// 获取授权信息
		var user models.User
		err, userInfo := user.CheckApiKey(auth)
		if err != nil {
			response := utils.GetResponse(nil, utils.UserNotExist, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}
		if userInfo.Status == 0 || (userInfo.MaturityTime < time.Now().Unix() && userInfo.DappMaturityTime < time.Now().Unix()) {
			response := utils.GetResponse(nil, utils.UserNotMemberOrStop, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}

		c.Next()
	}

}

func VerifyDel() gin.HandlerFunc {
	return func(c *gin.Context) {

		contentType := c.Request.Header.Get("Content-Type")
		var userId string
		var address string
		var nonce string
		var timestamp string
		var sign string
		var bodyJson string

		language := c.Request.Header.Get("language")
		if language == "" {
			language = "zh-tw"
		}

		if contentType != "application/json" {
			bodyJson = c.PostForm("body")
			if bodyJson == "" {
				response := utils.GetResponse(nil, utils.ParseDataError, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			nonce = c.PostForm("nonce")
			if nonce == "" {
				response := utils.GetResponse(nil, utils.NonceNotEmpty, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			timestamp = c.PostForm("timestamp")
			if timestamp == "" {
				response := utils.GetResponse(nil, utils.TimeStampNotEmpty, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			sign = c.PostForm("sign")
			if sign == "" {
				response := utils.GetResponse(nil, utils.SignNotEmpty, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}

			//解析body
			var body models.Body
			err := json.Unmarshal([]byte(bodyJson), &body)
			if err != nil {
				response := utils.GetResponse(nil, utils.BodyParseError, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}

			address = body.Address

			userId = body.MerchantId

		} else {
			var requestParam models.RequestParam
			err := c.ShouldBindJSON(&requestParam)
			if err != nil {
				response := utils.GetResponse(err, utils.ParamBindError, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}

			var body models.Body
			err = json.Unmarshal([]byte(requestParam.Body), &body)
			if err != nil {
				response := utils.GetResponse(err, utils.BodyParseError, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}

			if requestParam.Nonce == "" {
				response := utils.GetResponse(nil, utils.NonceNotEmpty, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			if requestParam.Timestamp == "" {
				response := utils.GetResponse(nil, utils.TimeStampNotEmpty, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			if requestParam.Sign == "" {
				response := utils.GetResponse(nil, utils.SignNotEmpty, nil, language)
				c.JSON(http.StatusOK, response)
				c.Abort()
				return
			}
			userId = body.MerchantId
			address = body.Address
			nonce = requestParam.Nonce
			timestamp = requestParam.Timestamp
			sign = requestParam.Sign
			bodyJson = requestParam.Body
		}

		//查询用户信息
		user := new(models.User)
		//string转ObjectId
		objId, err := primitive.ObjectIDFromHex(userId)
		if err != nil {
			response := utils.GetResponse(err, utils.ParseDataError, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}
		userClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")
		err = userClient.FindOne(context.TODO(), bson.D{{"_id", objId}}).Decode(&user)
		if err != nil {
			response := utils.GetResponse(err, utils.GetError, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}

		c.Set("user_id", userId)
		c.Set("address", address)
		c.Set("language", language)

		//验证签名
		isOk := tools.VerifySign(bodyJson, user.ApiKey, nonce, timestamp, sign)
		if !isOk {
			response := utils.GetResponse(nil, utils.SignError, nil, language)
			c.JSON(http.StatusOK, response)
			c.Abort()
			return
		}

		c.Next()
	}
}

// CustomResponseWriter 自定义响应记录器
type CustomResponseWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

func (w CustomResponseWriter) Write(b []byte) (int, error) {
	w.body.Write(b)                  // 将响应数据写入缓冲区
	return w.ResponseWriter.Write(b) // 写入实际响应
}

// LoggerMiddleware 自定义日志中间件
func LoggerMiddleware(logger *zap.Logger) gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now()
		// 替换默认的 ResponseWriter
		customWriter := &CustomResponseWriter{
			ResponseWriter: c.Writer,
			body:           bytes.NewBufferString(""),
		}
		c.Writer = customWriter
		// 处理请求
		c.Next()

		// 获取请求参数
		var params string
		if c.Request.Method == "GET" {
			params = c.Request.URL.Query().Encode()
		} else {
			// 处理 POST 请求
			contentType := c.Request.Header.Get("Content-Type")

			if contentType == "application/json" {
				// 处理 JSON 请求
				var jsonData map[string]interface{}
				if err := c.ShouldBindJSON(&jsonData); err != nil {
					log.Println("err:", err)
					return
				}
				jsonBytes, _ := json.Marshal(jsonData)
				params = string(jsonBytes)
			} else if contentType == "multipart/form-data" {
				// 处理 form-data 请求
				if err := c.Request.ParseMultipartForm(10 << 20); err != nil {
					c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
					return
				}

				// 获取表单字段
				for key, values := range c.Request.PostForm {
					for _, value := range values {
						params += fmt.Sprintf("%s=%s&", key, value)
					}
				}
				// 去掉最后一个 '&'
				if len(params) > 0 {
					params = params[:len(params)-1]
				}
			}
		}

		// 记录请求日志
		logger.Info("请求日志",
			zap.String("method", c.Request.Method),
			zap.String("path", c.Request.URL.Path),
			zap.String("params", params),
			zap.Int("status", c.Writer.Status()),
			zap.Duration("latency", time.Since(start)),
			zap.String("client_ip", c.ClientIP()),
			zap.Time("request_time", start),                    // 记录请求时间
			zap.String("response", customWriter.body.String()), // 记录响应数据
		)
	}
}
